#include "minunit.h"
#include <lcthw/list.h>
#include <assert.h>

static List *list = NULL;
char *test1 = "test1 data";
char *test2 = "test2 data";
char *test3 = "test3 data";
char *test[] = {"test1 data","test2 data","test3 data","test4 data","test5 data","test6 data"};

char *test_create()
{
    list = List_create();
    mu_assert(list != NULL, "Failed to create list.");

    return NULL;
}


char *test_destroy()
{
    List_clear_destroy(list);

    return NULL;

}


char *test_push_pop()
{
    List_push(list, test1);
    mu_assert(List_last(list) == test1, "Wrong last value.");

    List_push(list, test2);
    mu_assert(List_last(list) == test2, "Wrong last value");

    List_push(list, test3);
    mu_assert(List_last(list) == test3, "Wrong last value.");
    mu_assert(List_count(list) == 3, "Wrong count on push.");

    char *val = List_pop(list);
    mu_assert(val == test3, "Wrong value on pop.");

    val = List_pop(list);
    mu_assert(val == test2, "Wrong value on pop.");

    val = List_pop(list);
    mu_assert(val == test1, "Wrong value on pop.");
    mu_assert(List_count(list) == 0, "Wrong count after pop.");

    return NULL;
}

char *test_unshift()
{
    List_unshift(list, test1);
    mu_assert(List_first(list) == test1, "Wrong first value.");

    List_unshift(list, test2);
    mu_assert(List_first(list) == test2, "Wrong first value");

    List_unshift(list, test3);
    mu_assert(List_first(list) == test3, "Wrong last value.");
    mu_assert(List_count(list) == 3, "Wrong count on unshift.");

    return NULL;
}

char *test_remove()
{
    // we only need to test the middle remove case since push/shift
    // already tests the other cases

    char *val = List_remove(list, list->first->next);
    mu_assert(val == test2, "Wrong removed element.");
    mu_assert(List_count(list) == 2, "Wrong count after remove.");
    mu_assert(List_first(list) == test3, "Wrong first after remove.");
    mu_assert(List_last(list) == test1, "Wrong last after remove.");

    return NULL;
}


char *test_shift()
{
    mu_assert(List_count(list) != 0, "Wrong count before shift.");

    char *val = List_shift(list);
    mu_assert(val == test3, "Wrong value on shift.");

    val = List_shift(list);
    mu_assert(val == test1, "Wrong value on shift.");
    mu_assert(List_count(list) == 0, "Wrong count after shift.");

    return NULL;
}
/****** TODO  *****/
char *test_copy()
{
    int i=0;
    List_push(list, test[0]);
    List_push(list, test[1]);
    List_push(list, test[2]);
    List *listnew = List_copy(list);

    LIST_FOREACH(listnew, first, next, cur){
        mu_assert(cur->value == test[i++], "Wrong value on copy.");
    //    printf("%s\n",(char*)cur->value);
    }
  
    return NULL;
}
char *test_join()
{
    int i=0;
    List * list1 = List_create();
    List_push(list1, test[0]);
    List_push(list1, test[1]);
    List_push(list1, test[2]);
    List *list2 = List_copy(list1);
    List_join(list1,list2);
    LIST_FOREACH(list1, first, next, cur){
//    printf("%s\n",(char*)cur->value);
        mu_assert(cur->value == test[(i++)%3], "Wrong value on copy.");
    }
  
    return NULL;
}

char *test_split()
{
    int i=0 , pos=2;
    List * listold = List_create();
    List * listnew = NULL;
    List_push(listold, test[0]);
    List_push(listold, test[1]);
    List_push(listold, test[2]);
    List_push(listold, test[3]);
    List_push(listold, test[4]);
    List_push(listold, test[5]);
    listnew = List_split(listold,pos);
    printf("LIST OLD\n");  
    LIST_FOREACH(listold, first, next, cur1){
        printf("%s\n",(char*)cur1->value);   
        mu_assert(cur1->value == test[i++], "Wrong value on split.");
    }
    mu_assert(listold->count == pos, "Wrong count on split.");
    mu_assert(listnew->count == 6-pos, "Wrong count on split.");
  
    printf("LIST NEW\n");  
    LIST_FOREACH(listnew, first, next, cur2){
        printf("%s\n",(char*)cur2->value);   
        mu_assert(cur2->value == test[i++], "Wrong value on split.");
    }



    return NULL;
}

char *all_tests() {
    mu_suite_start();

    // mu_run_test(test_create);
    // mu_run_test(test_push_pop);
    // mu_run_test(test_unshift);
    // mu_run_test(test_remove);
    // mu_run_test(test_shift);
    // mu_run_test(test_destroy);

    // mu_run_test(test_copy);
    // mu_run_test(test_join);
    // mu_run_test(test_split);
    List * listold = List_create();   
    List_push(listold, test[0]);
    List_push(listold, test[1]);
    List_push(listold, test[2]);
    List_push(listold, test[3]);
    List_push(listold, test[4]);
    List_push(listold, test[5]);
    List *left=NULL;
    List *right=NULL ;

    int middle = List_count(listold) / 2;
    right= List_split(listold,middle);
    LIST_FOREACH(right, first, next, cur1) {
        printf("right %s\n",(char *)cur1->value);
    }
    left = listold;
    LIST_FOREACH(left, first, next, cur2) {
        printf("left %s\n",(char *)cur2->value);
    }
    return NULL;
}

RUN_TESTS(all_tests);